package com.qzsoft.zhjd.common.utils;

import com.qzsoft.zhjd.common.model.MarshallDataYjkj;

/**
 * 云检科技（北京申克路业仪器有限公司）
 * 马歇尔稳定度试验仪数据解析器
 * 根据通信协议解析试验实时数据和试验最终结果
 */
public class MarshallStabilityParserYjkjUtils {

    // 协议常量定义
    private static final byte HEADER1 = (byte) 0xFA;
    private static final byte HEADER2 = (byte) 0xFB;
    private static final byte HEADER3 = (byte) 0xFC;
    public static final int DATA_TYPE_REAL_TIME = 0xA4;  // 试验实时数据
    public static final int DATA_TYPE_FINAL_RESULT = 0xA7; // 试验最终结果

    /**
     * 解析16进制字符串数据
     * @param hexString 16进制字符串，可以包含空格或直接连接
     * @return 解析后的马歇尔数据对象
     * @throws IllegalArgumentException 当数据格式错误时抛出异常
     */
    public static MarshallDataYjkj parse(String hexString) {
        if (hexString == null || hexString.trim().isEmpty()) {
            throw new IllegalArgumentException("输入数据不能为空");
        }

        // 清理输入字符串，移除空格
        String cleanHex = hexString.replaceAll("\\s+", "").toUpperCase();

        // 验证是否为有效的16进制字符串
        if (!cleanHex.matches("[0-9A-F]+")) {
            throw new IllegalArgumentException("输入包含无效的16进制字符");
        }

        // 转换16进制字符串为字节数组
        byte[] data = hexStringToByteArray(cleanHex);

        return parse(data);
    }

    /**
     * 解析字节数组数据
     * @param data 原始字节数据
     * @return 解析后的马歇尔数据对象
     */
    public static MarshallDataYjkj parse(byte[] data) {
        if (data == null || data.length < 7) {
            throw new IllegalArgumentException("数据长度不足，无法解析");
        }

        // 检查帧头
        if (data[0] != HEADER1 || data[1] != HEADER2 || data[2] != HEADER3) {
            throw new IllegalArgumentException("无效的帧头");
        }

        // 获取数据长度（第4个字节）
        int dataLength = data[3] & 0xFF;

        // 验证数据长度
        if (data.length < 3 + dataLength) { // 头3字节+长度1字节+数据长度+校验和1字节
            throw new IllegalArgumentException("数据长度与声明长度不符");
        }

        // 计算校验和
        boolean checksumValid = validateChecksum(data);

        // 获取仪器代码（第5个字节） 没有机器代码
        int instrumentCode = data[4] & 0xFF;

        // 获取数据类型标识（第6个字节）
        int dataType = data[5] & 0xFF;

        MarshallDataYjkj result = new MarshallDataYjkj();
        result.setInstrumentCode(instrumentCode);
        result.setDataType(dataType);
        result.setValid(checksumValid);

        // 根据数据类型进行解析
        if (dataType == DATA_TYPE_REAL_TIME) {
            parseRealTimeData(data, result);
        } else if (dataType == DATA_TYPE_FINAL_RESULT) {
            parseFinalResultData(data, result);
        } else {
            throw new IllegalArgumentException("未知的数据类型: 0x" + String.format("%02X", dataType));
        }

        return result;
    }

    /**
     * 解析试验实时数据 (0xA4)
     */
    private static void parseRealTimeData(byte[] data, MarshallDataYjkj result) {
        // 数据格式：0xFA 0xFB 0xFC 0x08 0x01 0xA4 FLAG DS(2) DF(2) SUM
        if (data.length < 12) {
            throw new IllegalArgumentException("试验实时数据长度不足");
        }

        // 数据标志 FLAG（第7个字节）
        int flag = data[6] & 0xFF;
        result.setFlag(flag);

        // 稳定度值 DS，2字节无符号二进制数，高字节在前
        int dsHigh = data[7] & 0xFF;
        int dsLow = data[8] & 0xFF;
        int dsValue = (dsHigh << 8) | dsLow;
        double stability = dsValue / 100.0; // 2位小数
        result.setStability(stability);

        // 流值 DF，2字节无符号二进制数，高字节在前
        int dfHigh = data[9] & 0xFF;
        int dfLow = data[10] & 0xFF;
        int dfValue = (dfHigh << 8) | dfLow;
        double flow = dfValue / 100.0; // 2位小数
        result.setFlow(flow);
    }

    /**
     * 解析试验最终结果 (0xA7)
     */
    private static void parseFinalResultData(byte[] data, MarshallDataYjkj result) {
        // 数据格式：0xFA 0xFB 0xFC 0x07 0x01 0xA7 DS(2) DF(2) SUM
        if (data.length < 11) {
            throw new IllegalArgumentException("试验最终结果数据长度不足");
        }

        // FLAG字段在最终结果中不存在
        result.setFlag(null);

        // 稳定度值 DS，2字节无符号二进制数，高字节在前
        int dsHigh = data[6] & 0xFF;
        int dsLow = data[7] & 0xFF;
        int dsValue = (dsHigh << 8) | dsLow;
        double stability = dsValue / 100.0; // 2位小数
        result.setStability(stability);

        // 流值 DF，2字节无符号二进制数，高字节在前
        int dfHigh = data[8] & 0xFF;
        int dfLow = data[9] & 0xFF;
        int dfValue = (dfHigh << 8) | dfLow;
        double flow = dfValue / 100.0; // 2位小数
        result.setFlow(flow);
    }

    /**
     * 校验和验证
     * 校验和为除去校验和本身之外所有数据的无符号相加保留低8位的数据
     */
    private static boolean validateChecksum(byte[] data) {
        int calculatedSum = 0;

        // 计算从帧头到校验和前一个字节的所有数据的无符号和
        for (int i = 0; i < data.length - 1; i++) {
            calculatedSum += data[i] & 0xFF;
        }

        // 保留低8位
        calculatedSum &= 0xFF;

        // 获取实际的校验和（最后一个字节）
        int actualSum = data[data.length - 1] & 0xFF;

        return calculatedSum == actualSum;
    }

    /**
     * 将16进制字符串转换为字节数组
     */
    private static byte[] hexStringToByteArray(String hexString) {
        int len = hexString.length();
        if (len % 2 != 0) {
            throw new IllegalArgumentException("16进制字符串长度必须为偶数");
        }

        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            String byteStr = hexString.substring(i, i + 2);
            data[i / 2] = (byte) Integer.parseInt(byteStr, 16);
        }
        return data;
    }
}
